#include "inverseJulia2.h"

#include <boost/random.hpp>

namespace fractals {
	using namespace boost;

	const unsigned int MAX_DEPTH=18;
	const float minX=-2, maxX=2, minY=-2, maxY=2;

	static variate_generator<mt19937, uniform_int<> > boolGen(mt19937(), uniform_int<>(0,1));

	static complex<float> randomComplex() {
		typedef mt19937 R;
		typedef uniform_real<float> D;

		static variate_generator<R, D> rng(R(), D(-1, 1));

		return complex<float>(rng(), rng());
	}

	InverseJulia2::InverseJulia2(complex<float> c) : dirty(true), c(c) {

	}

	void InverseJulia2::draw(bool &didClear) {
		didClear=dirty;		

		if(dirty) {
			glClear(GL_COLOR_BUFFER_BIT);
			check();
		}
		dirty=false;
		
		glColor4d(1, 1, 1, .25);
		
		draw(randomComplex(), 0);
	}

	void InverseJulia2::resize(unsigned int w, unsigned int h){
		centerFitRectagle(w, h, minX, maxX, minY, maxY);

		dirty=true;
	}
	
	static bool stuck(float x, float y) {
		vec3 p=project(x, y, 0);

		unsigned char color;
		glReadPixels((int)p[0], (int)p[1], 1, 1, GL_LUMINANCE, GL_UNSIGNED_BYTE, &color);

		return color > 200;
	}

	void InverseJulia2::draw(complex<float> z, unsigned int depth) const {
		float x=z.real(), y=z.imag();

		if(stuck(x, y)) return;

		float mag=(float)depth/(float)MAX_DEPTH;

		mag *= mag;

		glColor4f(1, 1, 1, mag);
		glBegin(GL_POINTS);
		glVertex2f(x, y);
		glEnd();

		z=sqrt(z-c);

		if(depth++ < MAX_DEPTH) {
			draw(z, depth);
			draw(-z, depth);
		}
	}
}